package com.ruoyi.project.payUtils.zfb;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayFundTransUniTransferModel;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.domain.BankcardExtInfo;
import com.alipay.api.domain.Participant;
import com.alipay.api.request.AlipayFundTransUniTransferRequest;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.project.content.FlowTypeEnum;
import com.ruoyi.project.utils.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;
import org.springframework.util.FileCopyUtils;

import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
@Slf4j
public class AliPayUtils {

    private static final Logger log = LoggerFactory.getLogger(AliPayUtils.class);


    private final static String ALIPAY_URL = "https://openapi.alipay.com/gateway.do";

    private final static String FORMAT = "json";

    private final static String CHARSET = "utf-8";

    private final static String SIGN_TYPE = "RSA2";

    //private final static String PrivateKey = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCg2A1BwqHwZ5hGW2cOjAuURpqzjnGyJ+yeZc5BlMfqdN2AB+Dz3WXRns228LRNhj076f3K+wZ4gKdO8KxbeQRtzDUVYgnRfkSGYI3/9Uvf/qYKyzehb67Wf3TwwQg/9oB/LywJ0XjdulzWa2JyS3jWCfsY4kWxnycSHgRaV4FBcInTeDIHiMGKj9b2gZmab7MO9fI3is5v8cJ6lhT3vHR8hKadhAc2pQxGayT+dH5gON7Mc+XpjfeE3dlN6sYb7NAyFai4HqyHeAfzUcki6FwgPvVD88+tyBHp3T/LUVX06V5PqyBdBRiaKr9kAg/EKbZSYm3P2ugzBweFK60eA2Q5AgMBAAECggEBAJPAxLTTAYXg9E41ar8/QOfN0BD/2kvJRyDe7pDqBpfHES6qjigXCpB8bAcQqODKXvfp5F0RKgmKTadDiWFiEwJ145GoBNLwRiyXB/rIMBItUAR8V7cx7A9Y+GitOlHftHyhLbg7N+efaecCsGXEFNWyR3q9aT5YsECBWIhQ+AjOzmxU2NnexeJfztoE8V4C/Z6Ig6MdLanxMS72WUNcJDGq/YRdzCEDcUexlf1++CR/rzn+kprFmz04w6F2aABATDkb52CSv/VV5J9kdnNkSjC903N2ukoDAAtUJ7zusON4RdQdpQjiGmBv6Rer6TD/xxgHKnAJLWVphK2fiGpLeXECgYEA1Egk/5NP/8Qqv8zQaGLeUSsxhVIF6Lr4iyUCZyyPUadR+Bek4m38l5IFNJqd+ntioOZzX0Cr65oqBWfDyVOwN/oJXBWFdiLt6Ikz0Dc8gn3GPi2ezJic9z3Us1HwWBvKKAuaFzgpfqyHpNJmZprE7vGhLW0boLsdEyMLSG/TXC0CgYEAwfgEMF8fnT9NH6jexmmpmK/GKwfDdkeY0y8WVEe4OLYrFhx4FD5GDo9h9uiMKmcVvxr3Dbtd49B1FgIdeR20zN+JSwWBh33p3OufyEicN14WGHI6Mr5MHUknfxz0KNVwUqx4g6mkpve8LV6w9PANQyMarvg7xF9T23XIr4NFE70CgYBHe+fhnITC9xcCMYE4tZpxsN7jK0TMIzIRASx2+91jPLnwll2y1iDKFaTlGu/56lTDI/dT6x45n1dpLJEUmbbskqlWNfUUXBzLQnCNPByHQL1iMNCZywaIh2y52ezabrk7lPSVvxbSDl07FpLfGF0arYl+F5DHJltbF2D0SpvdHQKBgQCu7p/QhCl95pYGpITtimOy2WuuaR0F8kJIy6GmttvVAa3QDjLZhuQlw3hFdqranweEx6vhzYY6rEi8ZYHxNjJVxpAKgde0u4ELhdEfjySb5pWkzHfiRa9dhhlB0Xn9zai0VumFTJy7HJewj0KmVEyRrPomrKcyTgrR1OL+LzRAPQKBgQCGQCPQSUlmxdn8FHgmCdms5YTk6F3WyubUdAAZfxZdBUWTYBa3uvzlTNbihlPSVzjkD3cv4twejkbISpzcdpqZm2kcSqyIxAgNwEhadQm7K8nSZtRy0X77mUg61alZurfwHfJYRzAa6E92OzvV88DjENQHDqhJj07zlZ5oQ6JwvQ==";

    @Value ("${pay.zfb.appid}")
    private String APP_ID;

    @Value ("${pay.zfb.privateKey}")
    private String PRIVATE_KEY;

    @Value ("${pay.zfb.alipayPublicKey}")
    private String ALIPAY_PUBLIC_KEY;

    @Value ("${pay.zfb.notifyUrl}")
    private String NOTIFY_URL;

    @Autowired
    ResourceLoader resourceLoader;



    public String getCharset () {
        return CHARSET;
    }

    public String getAlipayPublicKey () {
        return this.ALIPAY_PUBLIC_KEY;
    }

    public String getSigntype () {
        return SIGN_TYPE;
    }

    public String getAppid () {
        return this.APP_ID;
    }

    private AlipayClient alipayClient;

    public void initClient () {
        if (this.alipayClient == null) {
            try {

                //String filePath = ResourceUtils.getFile("classpath:xml/custInfo.xml").getPath();
                String path = System.getProperty("user.dir");
         /*   alipayClient= new DefaultAlipayClient(ALIPAY_URL, APP_ID,
                PRIVATE_KEY, FORMAT, CHARSET, ALIPAY_PUBLIC_KEY,
                SIGN_TYPE);*/
                //String path = RuoYiConfig.getProfile();
                CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
                //设置网关地址
                certAlipayRequest.setServerUrl(ALIPAY_URL);
                //设置应用Id
                certAlipayRequest.setAppId(this.APP_ID);
                //设置应用私钥
                certAlipayRequest.setPrivateKey(this.PRIVATE_KEY);
                //设置请求格式，固定值json
                certAlipayRequest.setFormat(FORMAT);
                //设置字符集
                certAlipayRequest.setCharset(CHARSET);
                //设置签名类型
                certAlipayRequest.setSignType(SIGN_TYPE);
                //设置应用公钥证书路径
                certAlipayRequest.setCertPath(path + "/file/new/appCertPublicKey_2021001164690199.crt");
                //设置支付宝公钥证书路径
                certAlipayRequest.setAlipayPublicCertPath(path + "/file/new/alipayCertPublicKey_RSA2.crt");
                //设置支付宝根证书路径
                certAlipayRequest.setRootCertPath(path + "/file/new/alipayRootCert.crt");
                this.alipayClient = new DefaultAlipayClient(certAlipayRequest);
            } catch (Exception e) {
                log.error("初始化服务异常：{}", e.getMessage());
            }
        }
    }

    /**
     * 调起支付
     *
     * @param orderId
     * @param type
     * @param totalAmount
     *
     * @return
     */
    public String pay (String orderId, Integer type, String totalAmount, Date createTime, Long userId, String userName)
            throws Exception {
        // 第三方支付
       /* BigDecimal amount = new BigDecimal(totalAmount).multiply(new BigDecimal(100));
        return leshuaPayUtil.alipay(type+"-"+orderId+"-"+ DateUtils.getNowDate().getTime(), amount.intValue(), createTime, userId, userName);*/

        // 原生支付
        //1用户立即支付，2充值余额支付, 3骑手保证金充值
        this.initClient();
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();

        AlipayTradeAppPayModel alipayTradeAppPayModel = new AlipayTradeAppPayModel();
        alipayTradeAppPayModel.setSubject(FlowTypeEnum.findByValue(type).getText());
        //alipayTradeAppPayModel.setOutTradeNo(type + "-" + orderId + "-" + DateUtils.getNowDate().getTime());
        alipayTradeAppPayModel.setOutTradeNo(orderId);
        //TODO 测试一分钱
        // log.debug("测试一分钱");
        // alipayTradeAppPayModel.setTotalAmount("0.01");
        alipayTradeAppPayModel.setTotalAmount(totalAmount);
        alipayTradeAppPayModel.setProductCode("QUICK_MSECURITY_PAY");
        alipayTradeAppPayModel.setBody("找零工");
        alipayTradeAppPayModel.setTimeExpire(
                DateUtils.parseDateToStr("yyyy-MM-dd HH:mm", DateUtils.addMinutes(createTime, 29)));
        request.setBizModel(alipayTradeAppPayModel);
        request.setNotifyUrl(this.NOTIFY_URL);
        try {

            AlipayTradeAppPayResponse alipayTradeAppPayResponse = this.alipayClient.sdkExecute(request);
            String body = alipayTradeAppPayResponse.getBody();
            return body;
        } catch (AlipayApiException e) {
            log.error("ali错误:" + e.getMessage());
            return e.getErrMsg();
        } catch (Exception e) {
            log.error("其他错误:" + e.getMessage());
            return e.getMessage();
        }
    }


    public String cashWithdrawal (String account, String userName, String withdrawalId, BigDecimal amount)
            throws Exception {
        //   System.out.println(amount.toString());
        this.initClient();
        //  AlipayFundTransToaccountTransferRequest request = new AlipayFundTransToaccountTransferRequest();
        AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();

        Map <String, Object> map = new HashMap();
        map.put("out_biz_no", withdrawalId);
        map.put("trans_amount", amount.setScale(2, RoundingMode.HALF_UP).toString());
        map.put("product_code", "TRANS_ACCOUNT_NO_PWD");
        map.put("biz_scene", "DIRECT_TRANSFER");
        map.put("order_title", "找零工支付宝提现");
        Map <String, Object> payeeinfo = new HashMap();
        payeeinfo.put("identity", account);
        payeeinfo.put("identity_type", "ALIPAY_LOGON_ID");
        payeeinfo.put("name", userName);
        map.put("payee_info", payeeinfo);
        
        
       /* map.put("out_biz_no",withdrawalId);
        map.put("payee_type","ALIPAY_LOGONID");
        map.put("payee_account",account);
        map.put("amount",amount.setScale(2, RoundingMode.HALF_UP).toString());
        //  map.put("amount",0.1);
        map.put("payee_real_name",userName);*/
        map.put("remark", "找零工支付宝提现");
        request.setBizContent(JsonUtils.console(map));
        //AlipayFundTransToaccountTransferResponse response = alipayClient.execute(request);
        AlipayFundTransUniTransferResponse response = this.alipayClient.certificateExecute(request);
        if (response.isSuccess()) {
            return response.getBody();
        } else {
            throw new RuntimeException("转账失败:" + response.getSubMsg());
        }
    }

    /**
     * 支付宝退款
     *
     * @param outTradeNo
     * @param amount
     * @param count
     *
     * @return
     */
    public String refund (String outTradeNo, String amount, Integer count) {
        // 第三方支付
        /* return leshuaPayUtil.refund(outTradeNo);*/

        // 原生支付
        this.initClient();
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        AlipayTradeRefundModel refundModel = new AlipayTradeRefundModel();
        refundModel.setOutTradeNo(outTradeNo);
        refundModel.setRefundAmount(amount);
        request.setBizModel(refundModel);
        AlipayTradeRefundResponse refundResponse = null;
        try {
            refundResponse = this.alipayClient.certificateExecute(request);
            log.debug("支付宝退款返回内容:" + refundResponse.getMsg());
            if (refundResponse.isSuccess()) {
                return refundResponse.getBody();
            } else {
                if (count < 5) {
                    return this.refund(outTradeNo, amount, ++count);
                } else {
                    return "";
                }
            }
        } catch (AlipayApiException e) {
            log.error(e.getErrMsg());
            if (count < 5) {
                return this.refund(outTradeNo, amount, ++count);
            } else {
                return "";
            }
        }
    }

    /**
     * 订单查询
     *
     * @param outTradeNo
     *         交易号
     *
     * @return
     */
    public String orderQuery (String outTradeNo) {
        this.initClient();

        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        AlipayTradeQueryModel model = new AlipayTradeQueryModel();
        model.setOutTradeNo(outTradeNo);
        request.setBizModel(model);

        try {
            AlipayTradeQueryResponse response = this.alipayClient.certificateExecute(request);

            if (!response.isSuccess()) {
                log.info("支付宝订单查询失败，{}", response.getBody());
                return response.getSubMsg();
            }
        } catch (Exception e) {
            log.info("[支付宝]交易记录查询失败", e);
        }

        return "查询成功";
    }

    /**
     * 获取文件路径
     *
     * @param name
     *
     * @return
     */
    public String getCertContentByPath (String name) {
        InputStream inputStream = null;
        String content = null;
        try {
            inputStream = this.getClass().getClassLoader().getResourceAsStream(name);
            content     = new String(FileCopyUtils.copyToByteArray(inputStream));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return content;
    }

    /**
     * 获取文件路径
     *
     * @param name
     *
     * @return
     */
    public String getFilePath (String name) {
        String serverPath = this.getClass().getResource("/").getPath();
        return serverPath + name;
    }

    /**
     * 转账到银行卡
     * @param outBizNo 流水号
     * @param transAmount  金额
     * @param bankNo   银行卡号
     * @param realName  真实姓名
     * @param bankInstName  银行名称
     * @return
     * @throws AlipayApiException
     */
    public AlipayFundTransUniTransferResponse executeWithdrawalBankCard(String outBizNo,String transAmount,String bankNo,String realName,
            String bankInstName)
            throws AlipayApiException {
        this.initClient ();
        AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
        AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
        //商家侧唯一订单号，由商家自定义。对于不同转账请求，商家需保证该订单号在自身系统唯一。
        model.setOutBizNo(outBizNo);
        model.setRemark("单笔转账");
        //业务场景，单笔无密转账到银行卡固定为DIRECT_TRANSFER
        model.setBizScene("DIRECT_TRANSFER");
        //银行信息
        Participant payeeInfo = new Participant();
        //参与方的标识，单笔无密转账到银行卡固定为收款方银行卡号
        payeeInfo.setIdentity(bankNo);
        BankcardExtInfo bankcardExtInfo = new BankcardExtInfo();
        bankcardExtInfo.setInstName(bankInstName);
        bankcardExtInfo.setAccountType("1");
        payeeInfo.setBankcardExtInfo(bankcardExtInfo);
        //参与方的标识类型，单笔无密转账到银行卡固定为BANKCARD_ACCOUNT
        payeeInfo.setIdentityType("BANKCARD_ACCOUNT");
        //收款方银行账户名称
        payeeInfo.setName(realName);
        model.setPayeeInfo(payeeInfo);
        //订单总金额，单位为元，不支持千位分隔符，精确到小数点后两位，取值范围[0.10,100000000]
        model.setTransAmount(transAmount);
        //产品码，单笔无密转账到银行卡固定为TRANS_BANKCARD_NO_PWD
        model.setProductCode("TRANS_ACCOUNT_NO_PWD");
        //转账业务的标题，用于在支付宝用户的账单里显示
        model.setOrderTitle("找零工平台结算");
        request.setBizModel(model);

        AlipayFundTransUniTransferResponse response = alipayClient.certificateExecute(request);
        System.out.println(response.getBody());
        if (response.isSuccess()) {
            System.out.println("调用成功");
        } else {
            System.out.println("调用失败");
            // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
            // String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
            // System.out.println(diagnosisUrl);
        }
        return response;
    }


    public static void main(String[] args) throws AlipayApiException {
        String privateKey = "<-- 请填写您的应用私钥，例如：MIIEvQIBADANB ... ... -->";
        CertAlipayRequest alipayConfig = new CertAlipayRequest();
        alipayConfig.setPrivateKey(privateKey);
        alipayConfig.setServerUrl("https://openapi.alipay.com/gateway.do");
        alipayConfig.setAppId("<-- 请填写您的AppId，例如：2019091767145019 -->");
        alipayConfig.setCharset("UTF8");
        alipayConfig.setSignType("RSA2");
        alipayConfig.setEncryptor("");
        alipayConfig.setFormat("json");
        alipayConfig.setCertPath("<-- 请填写您的应用公钥证书文件路径，例如：/foo/appCertPublicKey_2019051064521003.crt -->");
        alipayConfig.setAlipayPublicCertPath("<-- 请填写您的支付宝公钥证书文件路径，例如：/foo/alipayCertPublicKey_RSA2.crt -->");
        alipayConfig.setRootCertPath("<-- 请填写您的支付宝根证书文件路径，例如：/foo/alipayRootCert.crt -->");
        AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig);
        AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();


        AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
        //商家侧唯一订单号，由商家自定义。对于不同转账请求，商家需保证该订单号在自身系统唯一。
        model.setOutBizNo("201806300001");
        model.setRemark("单笔转账");
        model.setBusinessParams("{\"withdraw_timeliness\":\"T0\", \"sub_merchant_info\":\" {\\\"subMerchantName\\\":\\\"测试企业名称\\\",\\\"subMerchantMCC\\\":\\\"12345\\\"}\"} 注意：withdraw_timeliness 为转账到银行卡的预期到账时间，不传默认T+1到账。");
        model.setBizScene("DIRECT_TRANSFER");
        Participant payeeInfo = new Participant();
        payeeInfo.setIdentity("6222600260001072444");
        BankcardExtInfo bankcardExtInfo = new BankcardExtInfo();
        bankcardExtInfo.setAccountType("1");
        bankcardExtInfo.setInstBranchName("新街口支行");
        bankcardExtInfo.setInstProvince("江苏省");
        bankcardExtInfo.setInstName("招商银行");
        bankcardExtInfo.setBankCode("123456");
        bankcardExtInfo.setInstCity("南京市");
        payeeInfo.setBankcardExtInfo(bankcardExtInfo);
        payeeInfo.setIdentityType("BANKCARD_ACCOUNT");
        payeeInfo.setName("黄龙国际有限公司");
        model.setPayeeInfo(payeeInfo);
        model.setTransAmount("23.00");
        model.setProductCode("TRANS_ACCOUNT_NO_PWD");
        model.setOrderTitle("转账标题");
        request.setBizModel(model);
        AlipayFundTransUniTransferResponse response = alipayClient.certificateExecute(request);
        System.out.println(response.getBody());
        if (response.isSuccess()) {
            System.out.println("调用成功");
        } else {
            System.out.println("调用失败");
            // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
            // String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
            // System.out.println(diagnosisUrl);
        }
    }

}
